﻿using System.Collections.Generic;
using System.Windows.Forms;
using sinetd;
using sinetd.Services.Modbus;
using sinetd.Utilities;

namespace ModbusServer
{
    public partial class MainForm : Form
    {
        #region Server

        private Server srv;

        private void serverStart()
        {
            if (srv.Start())
            {
                writeToLog("ModbusServer.Start", "started ...");
            }
            else
            {
                writeToLog("ModbusServer.Start", "already running!");
            }
        }

        private void serverStop()
        {
            if (srv.Stop())
            {
                writeToLog("ModbusServer.Stop", "stoped ...");
                button_start_stop.Invoke(new Server.MessageLogEventHandler((string type, string txt) => { button_start_stop.Text = txt; }), new object[] { "", "Start" });
            }
            else
            {
                writeToLog("ModbusServer.Stop", "nothing to stop");
            }
        }

        #endregion

        private sinetd.Services.Modbus.DataModel dataModel;
        private sinetd.Services.Modbus.Service modbus_srv;
        private int RowLength = 16;

        public MainForm()
        {
            InitializeComponent();
            this.Icon = sinetd.Utilities.Assembly.GetIconLarge(sinetd.Utilities.Process.GetExeName(), 0);

            foreach (string name in System.Enum.GetNames(typeof(MemoryBanks)))
                comboBox1.Items.Add(name);

            dataModel = new DataModel(RowLength, 128, 128, 128, 128);
            dataModel.Reload();

            srv = new Server("ModbusServer.config.xml");

            List<string> ids = sinetd.Services.Manager.GetIds();
            if (ids.Count > 0)
            {
                modbus_srv = (sinetd.Services.Modbus.Service)sinetd.Services.Manager.GetById(ids[0]);
                modbus_srv.NewFrameHandler += new Service.FrameHandler(modbus_srv_NewFrameHandler);
                modbus_srv.DataModel = dataModel;
            }

            comboBox1.SelectedIndex = 0;
        }

        void modbus_srv_NewFrameHandler(ref Frame frame)
        {
            writeToLog("ModbusServer.NewFrameHandler", "\nRX:");
            frameToLog(frame);

            writeToLog("ModbusServer.NewFrameHandler", "Device: " + frame.Device);
            writeToLog("ModbusServer.NewFrameHandler", "Function: " + frame.FunctionCode);
            writeToLog("ModbusServer.NewFrameHandler", "From " + frame.DataInA + " for " + frame.DataInB + " bits.");

            frame = modbus_srv.Answer(frame);

            writeToLog("ModbusServer.NewFrameHandler", "\nTX:");
            frameToLog(frame);
        }

        private void frameToLog(Frame frame)
        {
            List<string[]> list = new List<string[]>();
            list.Add(frame.Encode().ToHexArray());
            string[] lines = list.PrintTable().Split('\n');
            for (int i = 0; i < lines.Length - 1; i++)
                writeToLog("ModbusServer.NewFrameHandler", lines[i]);
        }

        private void MainForm_FormClosing(object sender, FormClosingEventArgs e)
        {
            serverStop();
        }

        private void button_start_stop_Click(object sender, System.EventArgs e)
        {
            if (!srv.IsRunning)
            {
                serverStart();
                button_start_stop.Text = "Stop";
            }
            else
            {
                new System.Threading.Thread(() => { serverStop(); }).Start();
                writeToLog("ModbusServer.Stop", "trying to stop ...");
            }
        }

        private void writeToLog(string msgType, string msgText)
        {
            if (listBox1.InvokeRequired)
            {
                listBox1.Invoke(new Server.MessageLogEventHandler(writeToLog), new object[] { msgType, msgText });
            }
            else
            {
                if (msgType == "ModbusServer.NewFrameHandler")
                {
                    listBox1.Items.Add(msgText);

                    if (scrollToLastToolStripMenuItem.Checked)
                    {
                        int c = listBox1.Items.Count;
                        if (c > listBox1.Height / listBox1.ItemHeight)
                        {
                            listBox1.SelectedIndex = c - 1;
                            listBox1.SelectedIndex = -1;
                        }
                    }
                }
                else
                {
                    toolStripStatusLabel1.Text = msgText;
                }
            }
        }

        private void comboBox1_SelectedIndexChanged(object sender, System.EventArgs e)
        {
            dataGridView1.DataSource = null;
            dataModel.Reload();
            dataGridView1.DataSource = dataModel.Tables[comboBox1.SelectedIndex];
            for (int i = 0; i < dataGridView1.ColumnCount; i++)
                dataGridView1.Columns[i].SortMode = DataGridViewColumnSortMode.NotSortable;
        }

        private void dataGridView1_CellValueChanged(object sender, DataGridViewCellEventArgs e)
        {
            IDataTableReload p = (IDataTableReload)dataGridView1.DataSource;
            p.SetRawData(e.RowIndex, e.ColumnIndex, dataGridView1.Rows[e.RowIndex].Cells[e.ColumnIndex].Value);
        }
    }
}
